﻿using Microsoft.VisualStudio.TestTools.UnitTesting;
using SIR.Entities.Implementations;
using SIR.Web.API;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Net.Http;
using System.Net.Http.Headers;
using System.Web;
using System.Web.Hosting;
using System.Web.Http;
using System.Web.Http.Hosting;

namespace SIR.Web.Services.Tests
{
	[TestClass]
	public class SearchControllerTest
	{
		[TestInitialize]
		public void ConnectToDatabase()
		{
			// Connect to the database
			DAL.DataServer.Connect(System.Configuration.ConfigurationManager.ConnectionStrings["SIR"].ConnectionString);
			// Establish the HTTP conected
			SimpleWorkerRequest request = new SimpleWorkerRequest("", "", "", null, new StringWriter());
			HttpContext context = new HttpContext(request);
			HttpContext.Current = context;
		}

		[TestCleanup]
		public void DisconnectFromTheDatabase()
		{
			// Disconnect from the database
			DAL.DataServer.Disconnect();
		}

		[TestMethod]
		[SIRTestCategory(typeof(Area.Search), Area.Search.NoResults, 1, typeof(SearchController))]
		public void NoResults_ByImage()
		{
			// Search by image
			var controller = new SearchController();
			var response = controller.Image(90, 1);
			// Expect successful response but no items
			Assert.IsNotNull(response);
			Assert.IsNotNull(response.Content);
			Assert.AreEqual(0, response.Content.Count());
			Assert.IsFalse(response.Successful);
			Assert.AreNotEqual(string.Empty, response.Message);
		}

		[TestMethod]
		[SIRTestCategory(typeof(Area.Search), Area.Search.NoResults, 2, typeof(SearchController))]
		public void NoResults_ByColorBalance()
		{
			// Search by color
			var controller = new SearchController();
			var response = controller.Color("[FFFFFF,100,0]");
			// Expect successful response but no items
			Assert.IsNotNull(response);
			Assert.IsNotNull(response.Content);
			Assert.AreEqual(0, response.Content.Count());
			Assert.IsTrue(response.Successful);
			Assert.AreEqual(string.Empty, response.Message);
		}

		[TestMethod]
		[SIRTestCategory(typeof(Area.Search), Area.Search.NoResults, 3, typeof(SearchController))]
		public void NoResults_ByPattern()
		{
			// Search by pattern
			var controller = new SearchController();
			var response = controller.Pattern(90, 1);
			// Expect successful response but no items
			Assert.IsNotNull(response);
			Assert.IsNotNull(response.Content);
			Assert.AreEqual(0, response.Content.Count());
			Assert.IsTrue(response.Successful);
			Assert.AreEqual(string.Empty, response.Message);
		}

		[TestMethod]
		[SIRTestCategory(typeof(Area.Search), Area.Search.Error, 1, typeof(SearchController))]
		public void Error_ByImage()
		{
			// Search by invalid image id
			var controller = new SearchController();
			var response = controller.Image(90, -1);
			// Failed response with an error message
			Assert.IsNotNull(response);
			Assert.IsNotNull(response.Content);
			Assert.AreEqual(0, response.Content.Count());
			Assert.IsFalse(response.Successful);
			Assert.AreEqual("There was no image found with the ID of -1", response.Message);
		}

		[TestMethod]
		[SIRTestCategory(typeof(Area.Search), Area.Search.Error, 2, typeof(SearchController))]
		public void Error_ByColorBalance()
		{
			// Search by invalid color string
			var controller = new SearchController();
			var response = controller.Color("");
			// Failed response with error message
			Assert.IsNotNull(response);
			Assert.IsNotNull(response.Content);
			Assert.AreEqual(0, response.Content.Count());
			Assert.IsFalse(response.Successful);
			Assert.AreEqual("Invalid color definitions", response.Message);
		}

		[TestMethod]
		[SIRTestCategory(typeof(Area.Search), Area.Search.Error, 3, typeof(SearchController))]
		public void Error_ByPattern()
		{
			// Search by invalid pattern Id
			var controller = new SearchController();
			var response = controller.Pattern(90, -1);
			// Failed response with error message
			Assert.IsNotNull(response);
			Assert.IsNotNull(response.Content);
			Assert.AreEqual(0, response.Content.Count());
			Assert.IsFalse(response.Successful);
			Assert.AreEqual("There was no pattern found with the ID of -1", response.Message);
		}
		/// <summary>
		/// Upload the image based on the file name
		/// </summary>
		/// <param name="fileName">The name of the image file to upload</param>
		/// <returns>Teh image object for the upload image file</returns>
		private Image UploadImage(string fileName)
		{
			// Create the controller
			var controller = new ImageController();
			// Initalize the request
			controller.Request = new System.Net.Http.HttpRequestMessage();
			controller.Request.Properties.Add(HttpPropertyKeys.HttpConfigurationKey, new HttpConfiguration());
			// Get the full file name
			fileName = Path.Combine(Directory.GetCurrentDirectory(), "..\\..\\..\\SIR.Web.Tests\\Content", fileName);
			var formDataContent = new MultipartFormDataContent();
			// Upload the bytes of the image
			var fileContent = new StreamContent(new MemoryStream(System.IO.File.ReadAllBytes(fileName)));
			fileContent.Headers.ContentType = new MediaTypeHeaderValue("image/JPEG");
			var textContent = new StreamContent(new MemoryStream(System.Text.UnicodeEncoding.UTF8.GetBytes("")));
			// Add the content to the form data
			formDataContent.Add(fileContent, "\"file\"", fileName);
			// Set the content of the request
			controller.Request.Content = formDataContent;
			// Get the result of the upload
			var result = controller.PostFormData().Result;
			// Get the content of the response
			var content = ((ObjectContent<List<Response<Image>>>)(result.Content)).ReadAsAsync<List<Response<Image>>>().Result;
			// Return the image
			return content[0].Content as Image;
		}

		[TestMethod]
		[SIRTestCategory(typeof(Area.Search), Area.Search.ByImage, 1, typeof(SearchController))]
		public void Image_Beach()
		{
			// upload two beach images
			var image = UploadImage("SampleBeach.jpg");
			var image2 = UploadImage("SampleBeach2.jpg");
			var controller = new SearchController();
			// Start the processing
			while (SIR.Services.ImageProcessing.Processing.ProcessNextImage())
			{
				SIR.Services.ImageProcessing.Processing.FixedFailedQueueItems();
			};
			// Search for the images
			var response = controller.Image(10, image.Id);
			// Delete both images
			image.IsDeleted = true;
			DAL.DataServer.Save(image);
			image2.IsDeleted = true;
			DAL.DataServer.Save(image2);
			// verify one result was returned
			Assert.IsNotNull(response);
			Assert.IsNotNull(response.Content);
			Assert.AreEqual(1, response.Content.Count());
			Assert.IsTrue(response.Successful);
		}

		[TestMethod]
		[SIRTestCategory(typeof(Area.Search), Area.Search.ByImage, 2, typeof(SearchController))]
		public void Image_Forest()
		{
			// upload the images
			var image = UploadImage("SampleForest.jpg");
			var image2 = UploadImage("SampleForest2.jpg");
			var controller = new SearchController();
			// Start the processing
			while (SIR.Services.ImageProcessing.Processing.ProcessNextImage())
			{
				SIR.Services.ImageProcessing.Processing.FixedFailedQueueItems();
			};
			// Search for the images
			var response = controller.Image(10, image.Id);
			// Delete both images
			image.IsDeleted = true;
			DAL.DataServer.Save(image);
			image2.IsDeleted = true;
			DAL.DataServer.Save(image2);
			// verify one result was returned
			Assert.IsNotNull(response);
			Assert.IsNotNull(response.Content);
			Assert.AreEqual(1, response.Content.Count());
			Assert.IsTrue(response.Successful);
		}

		[TestMethod]
		[SIRTestCategory(typeof(Area.Search), Area.Search.ByImage, 3, typeof(SearchController))]
		public void Image_Sunset()
		{
			// upload the images
			var image = UploadImage("SampleSunset.jpg");
			var image2 = UploadImage("SampleSunset2.jpg");
			var controller = new SearchController();
			// Start the processing
			while (SIR.Services.ImageProcessing.Processing.ProcessNextImage())
			{
				SIR.Services.ImageProcessing.Processing.FixedFailedQueueItems();
			};
			// Search for the images
			var response = controller.Image(10, image.Id);
			// Delete both images
			image.IsDeleted = true;
			DAL.DataServer.Save(image);
			image2.IsDeleted = true;
			DAL.DataServer.Save(image2);
			// verify one result was returned
			Assert.IsNotNull(response);
			Assert.IsNotNull(response.Content);
			Assert.AreEqual(1, response.Content.Count());
			Assert.IsTrue(response.Successful);
		}

		[TestMethod]
		[SIRTestCategory(typeof(Area.Search), Area.Search.ByColorBalance, 1, typeof(SearchController))]
		public void Color_Beach()
		{
			// upload the image
			var image = UploadImage("SampleBeach2.jpg");
			var controller = new SearchController();
			// start the processing
			while (SIR.Services.ImageProcessing.Processing.ProcessNextImage())
			{
				SIR.Services.ImageProcessing.Processing.FixedFailedQueueItems();
			};
			// search by color
			var response = controller.Color("[4B99E7,20,30];[DAD5B8,10,30]");
			// delete the image
			image.IsDeleted = true;
			DAL.DataServer.Save(image);
			// verify one result was returned
			Assert.IsNotNull(response);
			Assert.IsNotNull(response.Content);
			Assert.AreEqual(1, response.Content.Count());
			Assert.IsTrue(response.Successful);
		}

		[TestMethod]
		[SIRTestCategory(typeof(Area.Search), Area.Search.ByColorBalance, 2, typeof(SearchController))]
		public void Color_Forest()
		{
			// upload the image
			var image = UploadImage("SampleForest2.jpg");
			var controller = new SearchController();
			// start the processing
			while (SIR.Services.ImageProcessing.Processing.ProcessNextImage())
			{
				SIR.Services.ImageProcessing.Processing.FixedFailedQueueItems();
			};
			// search by color
			var response = controller.Color("[284B09,25,25]");
			// delete the image
			image.IsDeleted = true;
			DAL.DataServer.Save(image);
			// verify one result was returned
			Assert.IsNotNull(response);
			Assert.IsNotNull(response.Content);
			Assert.AreEqual(1, response.Content.Count());
			Assert.IsTrue(response.Successful);
		}

		[TestMethod]
		[SIRTestCategory(typeof(Area.Search), Area.Search.ByColorBalance, 3, typeof(SearchController))]
		public void Color_Sunset()
		{
			// upload the image
			var image = UploadImage("SampleSunset3.jpg");
			var controller = new SearchController();
			// start the processing
			while (SIR.Services.ImageProcessing.Processing.ProcessNextImage())
			{
				SIR.Services.ImageProcessing.Processing.FixedFailedQueueItems();
			};
			// search by color
			var response = controller.Color("[B24B02,10,25]");
			// delete the image
			image.IsDeleted = true;
			DAL.DataServer.Save(image);
			// verify one result was returned
			Assert.IsNotNull(response);
			Assert.IsNotNull(response.Content);
			Assert.AreEqual(1, response.Content.Count());
			Assert.IsTrue(response.Successful);
		}

		[TestMethod]
		[SIRTestCategory(typeof(Area.Search), Area.Search.ByPattern, 1, typeof(SearchController))]
		public void Pattern_Beach()
		{
			// upload the image
			var image = UploadImage("SampleBeach2.jpg");
			var controller = new SearchController();
			// start the processing
			while (SIR.Services.ImageProcessing.Processing.ProcessNextImage())
			{
				SIR.Services.ImageProcessing.Processing.FixedFailedQueueItems();
			};
			// search by pattern
			var response = controller.Pattern(10, 13);
			// delete the image
			image.IsDeleted = true;
			DAL.DataServer.Save(image);
			// verify one result returned
			Assert.IsNotNull(response);
			Assert.IsNotNull(response.Content);
			Assert.AreEqual(1, response.Content.Count());
			Assert.IsTrue(response.Successful);
		}

		[TestMethod]
		[SIRTestCategory(typeof(Area.Search), Area.Search.ByPattern, 2, typeof(SearchController))]
		public void Pattern_Forest()
		{
			// upload the image
			var image = UploadImage("SampleForest2.jpg");
			var controller = new SearchController();
			// start the processing
			while (SIR.Services.ImageProcessing.Processing.ProcessNextImage())
			{
				SIR.Services.ImageProcessing.Processing.FixedFailedQueueItems();
			};
			// search by pattern
			var response = controller.Pattern(10, 15);
			// delete the image
			image.IsDeleted = true;
			DAL.DataServer.Save(image);
			// verify one result returned
			Assert.IsNotNull(response);
			Assert.IsNotNull(response.Content);
			Assert.AreEqual(1, response.Content.Count());
			Assert.IsTrue(response.Successful);
		}

		[TestMethod]
		[SIRTestCategory(typeof(Area.Search), Area.Search.ByPattern, 3, typeof(SearchController))]
		public void Pattern_Sunset()
		{
			// upload the image
			var image = UploadImage("SampleSunset3.jpg");
			var controller = new SearchController();
			// start the processing
			while (SIR.Services.ImageProcessing.Processing.ProcessNextImage())
			{
				SIR.Services.ImageProcessing.Processing.FixedFailedQueueItems();
			};
			// search by pattern
			var response = controller.Pattern(10, 16);
			// delete the image
			image.IsDeleted = true;
			DAL.DataServer.Save(image);
			// verify one result returned
			Assert.IsNotNull(response);
			Assert.IsNotNull(response.Content);
			Assert.AreEqual(1, response.Content.Count());
			Assert.IsTrue(response.Successful);
		}
	}
}
